<template>
	<div class="map">
		<div id="container" />
		<div class="tool-nav">
			<div @click="toolClick('enlarge')" class="nav-item" title="放大">
				<svg t="1691484120795" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5104" width="32" height="32"><path d="M640 456h-118.4V320a32 32 0 0 0-64 0v136H320a32 32 0 0 0 0 64h137.6V640a32 32 0 1 0 64 0v-120H640a32 32 0 1 0 0-64z" p-id="5105"></path><path d="M919.264 905.984l-138.912-138.912C851.808 692.32 896 591.328 896 480c0-229.376-186.624-416-416-416S64 250.624 64 480s186.624 416 416 416c95.008 0 182.432-32.384 252.544-86.208l141.44 141.44a31.904 31.904 0 0 0 45.248 0 32 32 0 0 0 0.032-45.248zM128 480C128 285.92 285.92 128 480 128s352 157.92 352 352-157.92 352-352 352S128 674.08 128 480z" p-id="5106"></path></svg>
			</div>
			<div @click="toolClick('reduce')" class="nav-item" title="缩小">
				<svg t="1691484136916" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6088" width="32" height="32"><path d="M919.264 905.984l-138.912-138.912C851.808 692.32 896 591.328 896 480c0-229.376-186.624-416-416-416S64 250.624 64 480s186.624 416 416 416c95.008 0 182.432-32.384 252.544-86.208l141.44 141.44a31.904 31.904 0 0 0 45.248 0 32 32 0 0 0 0.032-45.248zM128 480C128 285.92 285.92 128 480 128s352 157.92 352 352-157.92 352-352 352S128 674.08 128 480z" p-id="6089"></path><path d="M625.792 448H336a32 32 0 0 0 0 64h289.792a32 32 0 1 0 0-64z" p-id="6090"></path></svg>
			</div>
			<div @click="toolClick('fixed')" class="nav-item" title="固定">
				<svg t="1691484253704" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8498" width="32" height="32"><path d="M935.15 375.34c0-25.38-9.88-49.23-27.83-67.17L727.96 128.8c-37.04-37.04-97.31-37.04-134.35 0L338.53 383.89l-72.74-30.44c-35.71-14.94-76.48-6.91-103.85 20.46l-38.15 38.15c-37.04 37.04-37.04 97.31 0 134.35L282 704.62 127.5 859.13c-13.67 13.67-13.67 35.83 0 49.5 6.83 6.83 15.79 10.25 24.75 10.25s17.92-3.42 24.75-10.25l154.5-154.51 158.21 158.21c17.94 17.94 41.8 27.83 67.18 27.83s49.23-9.88 67.17-27.83l38.15-38.15c27.37-27.37 35.4-68.14 20.46-103.85l-30.44-72.74L907.32 442.5c17.95-17.93 27.83-41.79 27.83-67.16z m-77.33 17.67l-262.2 262.2c-15.85 15.85-20.5 39.45-11.85 60.12l34.32 82.02c3.93 9.4 1.82 20.13-5.38 27.33l-38.15 38.15c-4.72 4.72-11 7.32-17.68 7.32s-12.96-2.6-17.68-7.32L173.29 496.91c-9.75-9.75-9.75-25.61 0-35.36l38.15-38.15c4.8-4.8 11.16-7.34 17.65-7.34 3.25 0 6.54 0.64 9.68 1.95l82.02 34.32c20.68 8.65 44.28 4 60.12-11.85l262.2-262.2c9.75-9.75 25.61-9.75 35.36 0l179.36 179.36c9.74 9.77 9.74 25.63-0.01 35.37z" p-id="8499"></path></svg>
			</div>
			<div @click="toolClick('reset')" v-if="isZoomed" class="nav-item" title="重置">
				<svg t="1691484362015" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14076" width="32" height="32"><path d="M943.8 484.1c-17.5-13.7-42.8-10.7-56.6 6.8-5.7 7.3-8.5 15.8-8.6 24.4h-0.4c-0.6 78.3-26.1 157-78 223.3-124.9 159.2-356 187.1-515.2 62.3-31.7-24.9-58.2-54-79.3-85.9h77.1c22.4 0 40.7-18.3 40.7-40.7v-3c0-22.4-18.3-40.7-40.7-40.7H105.5c-22.4 0-40.7 18.3-40.7 40.7v177.3c0 22.4 18.3 40.7 40.7 40.7h3c22.4 0 40.7-18.3 40.7-40.7v-73.1c24.2 33.3 53 63.1 86 89 47.6 37.3 101 64.2 158.9 79.9 55.9 15.2 113.5 19.3 171.2 12.3 57.7-7 112.7-24.7 163.3-52.8 52.5-29 98-67.9 135.3-115.4 37.3-47.6 64.2-101 79.9-158.9 10.2-37.6 15.4-76 15.6-114.6h-0.1c-0.3-11.6-5.5-23.1-15.5-30.9zM918.7 135.2h-3c-22.4 0-40.7 18.3-40.7 40.7V249c-24.2-33.3-53-63.1-86-89-47.6-37.3-101-64.2-158.9-79.9-55.9-15.2-113.5-19.3-171.2-12.3-57.7 7-112.7 24.7-163.3 52.8-52.5 29-98 67.9-135.3 115.4-37.3 47.5-64.2 101-79.9 158.8-10.2 37.6-15.4 76-15.6 114.6h0.1c0.2 11.7 5.5 23.2 15.4 30.9 17.5 13.7 42.8 10.7 56.6-6.8 5.7-7.3 8.5-15.8 8.6-24.4h0.4c0.6-78.3 26.1-157 78-223.3 124.9-159.2 356-187.1 515.2-62.3 31.7 24.9 58.2 54 79.3 85.9h-77.1c-22.4 0-40.7 18.3-40.7 40.7v3c0 22.4 18.3 40.7 40.7 40.7h177.3c22.4 0 40.7-18.3 40.7-40.7V175.8c0.1-22.3-18.2-40.6-40.6-40.6z" p-id="14077"></path></svg>
			</div>
		</div>
	</div>
</template>

<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import data from "./data.js";

let scatterInstanceAll = [];

const ZOOM = 3.8;

export default {
	data() {
		return {
			// map:null,
			zoom: ZOOM,
			fixed: false,
		};
	},
	computed: {
		isZoomed() {
			return this.zoom !== ZOOM;
		}
	},
	async mounted() {
		await this.initMap();
		this.drawHeatMap();
	},
	methods: {
		/** @name 工具栏点击 **/
		toolClick(flag) {
			switch (flag) {
				case 'enlarge':
					this.zoom++;
					this.map.setZoom(this.zoom);
					break;
				case 'reduce':
					this.zoom--;
					this.map.setZoom(this.zoom);
					break;
				case 'fixed':
					this.fixed = !this.fixed;
					this.map.setStatus({
						doubleClickZoom: this.fixed,
						scrollWheel: this.fixed,
					});
					break;
				case 'reset':
					this.zoom = ZOOM;
					this.map.setZoom(this.zoom);
					break;
			}
		},
		/** @name 初始化地图 **/
		initMap() {
			return new Promise((resolve) => {
				window._AMapSecurityConfig = {
					securityJsCode: "",
				};
				AMapLoader.load({
					key: "",
					version: "2.0",
					plugins: ["AMap.HeatMap"],
				})
					.then((AMap) => {
						this.map = new AMap.Map("container", {
							center: [110.17293, 35.20173],
							zoom: this.zoom, // 缩放级别
						});
						this.map.on("complete", () => {
							resolve();
						});
					})
					.catch((e) => {
						console.log(e);
					});
			});
		},
		/** @name 根据地址从高德获取地址的经纬度信息 **/
		geoCode(address) {
			return new Promise((resolve) => {
				if (!geocoder) {
					geocoder = new window.AMap.Geocoder();
				}
				geocoder.getLocation(address, (status, result) => {
					if (status === "complete" && result.geocodes.length) {
						const lnglat = result.geocodes[0].location;
						resolve(lnglat);
					} else {
						console.warn("根据地址查询位置失败：" + address);
					}
				});
			});
		},
		/** @name 绘制热力地图 **/
		async drawHeatMap() {
			// 最大值
    	let max = 0;
			// 转化热力需要的数据格式
    	const heatData = [];
			for (const [index, address] of data.entries()) {
				// 寻找最大值
				if (max < address.count) {
					max = address.count;
				}
				// 经纬度
				let center = [address.lng, address.lat];
				// 兼容缺失经纬度坐标的数据
				if (!center[0] || !center[1]) {
					// 前端通过高德API自行查经纬度
					const result = await this.geoCode(address.append);
					center = [result.lng, result.lat];
					// 如果还是查不到经纬度，就放弃这个点
					if (!center[0] || !center[1]) continue;
				}
				if (center[0] && center[1]) {
					heatData.push({
						lng: +center[0],
						lat: +center[1],
						count: address.count,
					});
					const scatterInstance = new window.AMap.CircleMarker({
            center,
            radius: 6,
            zIndex: index,
            strokeWeight: 1,
            strokeColor: '#FFFFFF',
            strokeOpacity: 0,
            fillColor: 'blue',
            fillOpacity: 0,
            cursor: 'pointer',
            clickable: true,
            extData: {
              index,
              address,
            },
          });
					scatterInstance.setMap(this.map);
					scatterInstanceAll.push(scatterInstance);
					scatterInstance.on('mouseover', e => {
            const extData = e.target._opts.extData;
            // 点层级调大
            scatterInstanceAll[extData.index].setOptions({
              zIndex: scatterInstanceAll.length + 10,
              strokeOpacity: 1,
              fillOpacity: 0.8,
            });
          });
					scatterInstance.on('mouseout', e => {
            const extData = e.target._opts.extData;
            scatterInstanceAll[extData.index].setOptions({
              zIndex: extData.index,
              strokeOpacity: 0,
              fillOpacity: 0,
            });
          });
				}
			}
			const densityInstance = new window.AMap.HeatMap(this.map, {
				radius: 25,
				opacity: [0, 0.8],
				// 由外向内
				gradient: {
					0.2: 'blue',
					0.4: 'rgb(117, 211, 248)',
					0.6: 'rgb(0, 255, 0)',
					0.8: '#ffea00',
					1.0: 'red',
				},
				zIndex: 1,
			});
			densityInstance.setDataSet({
				data: heatData,
				max,
			});
		}
	},
}
</script>

<style scoped>
.map {
	width: 740px;
	height: 500px;
	position: relative;
	display: flex;
	justify-content: flex-start;
	align-items: flex-start;
}
#container {
	width: 100%;
	height: 100%;
}
.tool-nav {
	position: absolute;
  right: 12px;
  bottom: 12px;
  display: flex;
}
.nav-item {
	width: 30px;
  height: 30px;
  border-radius: 4px;
  background-color: rgba(0, 0, 0, 0.5);
  margin-left: 12px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  line-height: 1;
  font-size: 17px;
	fill: #fff;
}
.nav-item .icon {
	width: 20px;
	height: 20px;
}
</style>
